﻿//------------------------------------------------------------------------------
//  Namespace: FruitVentDesign.Controls
//  
//  Function： N/A
//  Name： Tree
//  
//  Ver       Time                     Author
//  0.10      2021/6/23 18:24:48      FruitVent
//
//  此代码版权归作者本人FruitVent所有
//  源代码使用协议遵循本仓库的开源协议及附加协议，若本仓库没有设置，则按MIT开源协议授权
//  CSDN博客：https://blog.csdn.net/weixin_39552347
//  源代码仓库：https://gitee.com/fruitvent
//  感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using FruitVentDesign.Utils;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace FruitVentDesign.Controls
{
    public class Tree : TreeView
    {
        public Tree()
        {
            // Loaded += Tree_Loaded;
        }

        private void Tree_Loaded(object sender, RoutedEventArgs e)
        {
            if (FilterCondition != null)
            {
                _ = GetTreeViewItem(this, FilterCondition, this);
            }
        }

        #region FilterCondition dependency property
        /// <summary>
        /// 筛选树形结构关键字
        /// </summary>
        public static readonly DependencyProperty FilterConditionKeyProperty = DependencyProperty.Register(
            "FilterConditionKey", typeof(string), typeof(Tree),
            new FrameworkPropertyMetadata(null));

        public static string GetFilterConditionKey(DependencyObject d)
        {
            return (string)d.GetValue(FilterConditionKeyProperty);
        }

        public static void SetFilterConditionKey(DependencyObject obj, string value)
        {
            obj.SetValue(FilterConditionKeyProperty, value);
        }

        /// <summary>
        /// 筛选条件
        /// </summary>
        public static readonly DependencyProperty FilterConditionProperty = DependencyProperty.Register(
           "FilterCondition",
           typeof(object),
           typeof(Tree),
           new PropertyMetadata(null, OnFilterConditionPropertyChanged));

        private static void OnFilterConditionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is Tree self)
            {
                if (e.OldValue != e.NewValue)
                {
                    GetTreeViewItem(self, e.NewValue, self);
                }
                // ExpandAndSelectItem(self, e.NewValue, self);
            }
        }

        public object FilterCondition
        {
            get { return GetValue(FilterConditionProperty); }
            set { SetValue(FilterConditionProperty, value); }
        }
        #endregion

        /// <summary>
        /// 获取当前节点下符合筛选条件的子元素
        /// </summary>
        /// <param name="container">当前节点</param>
        /// <param name="item">要查询的元素</param>
        /// <returns></returns>
        private static TreeViewItem GetTreeViewItem(ItemsControl container, object item, TreeView treeView)
        {
            if (container != null)
            {
                if (container.DataContext == null) return null;

                PropertyInfo property = container.DataContext.GetType().GetProperty(GetFilterConditionKey(treeView));
                string filterConditionValue = "";
                if (property != null)
                {
                    filterConditionValue = property.GetValue(container.DataContext).ToString();
                }
                //Console.WriteLine($"{filterConditionValue}, {item}");
                // 此处是筛选条件 可根据实际情况修改
                if (filterConditionValue.Equals(item))
                {
                    container.Focus();
                    ((TreeViewItem)container).IsSelected = true;
                    return container as TreeViewItem;
                }
                // 展开当前树节点
                if (container is TreeViewItem treeViewitem && !treeViewitem.IsExpanded)
                {
                    container.SetValue(TreeViewItem.IsExpandedProperty, true);
                }

                // 尝试生成ItemsPresenter和ItemsPanel。
                // 通过调用ApplyTemplate。 请注意，在虚拟化情况下，即使项目已标记
                // 扩展后我们仍然需要这样做去 
                // 重新生成视觉效果，因为它们可能已被虚拟化。

                _ = container.ApplyTemplate();
                ItemsPresenter itemsPresenter =
                    (ItemsPresenter)container.Template.FindName("ItemsHost", container);
                if (itemsPresenter != null)
                {
                    _ = itemsPresenter.ApplyTemplate();
                }
                else
                {
                    // Tree模板尚未命名ItemsPresenter， 
                    // 执行descendents找到子元素.
                    itemsPresenter = CommonUtil.FindVisualChild<ItemsPresenter>(container);
                    if (itemsPresenter == null)
                    {
                        container.UpdateLayout();

                        itemsPresenter = CommonUtil.FindVisualChild<ItemsPresenter>(container);
                    }
                }

                Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);

                // 确保已创建此面板的生成器。
                UIElementCollection children = itemsHostPanel.Children;

                for (int i = 0, count = container.Items.Count; i < count; i++)
                {
                    TreeViewItem subContainer;
                    if (itemsHostPanel is MyVirtualizingStackPanel virtualizingPanel)
                    {
                        // 将项目置于视图中 
                        // 将生成容器。
                        virtualizingPanel.BringIntoView(i);

                        subContainer =
                            (TreeViewItem)container.ItemContainerGenerator.
                            ContainerFromIndex(i);

                        //Console.WriteLine($"virtualizingPanel:{virtualizingPanel},subContainer:{subContainer}");

                    }
                    else
                    {
                        subContainer =
                            (TreeViewItem)container.ItemContainerGenerator.
                            ContainerFromIndex(i);

                        // Console.WriteLine($"subContainer:{subContainer}");

                        // Bring the item into view to maintain the 
                        // same behavior as with a virtualizing panel.
                        if (subContainer != null)
                        {
                            subContainer.BringIntoView();
                        }
                    }

                    if (subContainer != null)
                    {
                        // Search the next level for the object.
                        TreeViewItem resultContainer = GetTreeViewItem(subContainer, item, treeView);
                        if (resultContainer != null)
                        {
                            return resultContainer;
                        }
                        else
                        {
                            // 元素不在TreeViewItem中
                            // 折叠它 取消之前的选中
                            subContainer.IsExpanded = false;
                            subContainer.IsSelected = false;
                        }
                    }
                }
            }

            return null;
        }
    }

    /// <summary>
    /// 自定义VirtualizingStackPanelBr 用于获取树节点的所有子元素信息（此类随便放到程序能调用的地 
    ///方就行）
    /// </summary>
    public class MyVirtualizingStackPanel : VirtualizingStackPanel
    {
        /// <summary>
        /// Publically expose BringIndexIntoView.
        /// </summary>
        public void BringIntoView(int index)
        {

            this.BringIndexIntoView(index);
        }
    }
}
